home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Human Interface Toolbox / Calculator / CalcController.m < prev    next >
Encoding:
Text File  |  2000-10-06  |  6.8 KB  |  231 lines

  1. /*
  2.     File:       CalcController.m
  3.  
  4.     Contains:   xxx
  5.  
  6.     Written by: Andy Wildenberg
  7.  
  8.     Created:    Wed 09-Jul-1997
  9.  
  10.     Copyright:  (c)1997 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.         7/5/00    KG    Updated for Project Builder on DP4
  14.         9 July 97 -- first version of application
  15.     
  16.     You may incorporate this sample code into your applications without
  17.     restriction, though the sample code has been provided "AS IS" and the
  18.     responsibility for its operation is 100% yours.  However, what you are
  19.     not permitted to do is to redistribute the source as "DSC Sample Code"
  20.     after having made changes. If you're going to re-distribute the source,
  21.     we require that you make it clear in the source that the code was
  22.     descended from Apple Sample Code, but that you've made changes.
  23. */
  24.  
  25. #import "CalcController.h"
  26.  
  27. @implementation CalcController
  28.  
  29. - (void)clear:(id)sender
  30. {
  31.     [displayedNumber autorelease];
  32.     displayedNumber = [[NSDecimalNumber zero] retain];
  33.     [enteredNumber autorelease];
  34.     enteredNumber = [[NSDecimalNumber zero] retain];
  35.     [displayView setDoubleValue: 0];
  36.     [self endEditingNumber];
  37.     lastOperation = kNoOperator;
  38.     usedDecimalPoint = NO;
  39. }
  40.  
  41. - (void)equals:(id)sender
  42. {
  43.     if (enteringNumber)
  44.       {
  45.         [self endEditingNumber];
  46.         [self performLastOperation];
  47.         lastOperation = kNoOperator;
  48.         [displayView setStringValue: [displayedNumber stringValue]];
  49.       }
  50. }
  51.  
  52. - (void)insertDigit:(id)sender
  53. {
  54.     NSString* oldValue;
  55.  
  56.     if (!enteringNumber)
  57.       {
  58.         [self beginEditingNumber];
  59.       }
  60.  
  61.  
  62.     oldValue = [displayView stringValue];
  63.     [displayView setStringValue: [oldValue stringByAppendingString: [sender title]]];
  64. }
  65.  
  66. - (void)beginEditingNumber
  67. {
  68.     enteringNumber = YES;
  69.     usedDecimalPoint = NO;
  70.     [displayView setStringValue: @""];
  71.     [enteredNumber autorelease];
  72.     enteredNumber = [displayedNumber copy]; 
  73. }
  74.  
  75. - (void)endEditingNumber
  76. {
  77.     enteringNumber = NO;
  78.     usedDecimalPoint = NO;
  79.  
  80.     [displayedNumber autorelease];
  81.     displayedNumber = [NSDecimalNumber decimalNumberWithString: [displayView stringValue]];
  82.     [displayedNumber retain];
  83. }
  84.  
  85. - (void)decimalPoint:(id)sender
  86. {
  87.     NSString* oldValue;
  88.  
  89.     if (!usedDecimalPoint)
  90.       {
  91.         usedDecimalPoint = YES;
  92.         if (!enteringNumber)
  93.           {
  94.             [self beginEditingNumber];
  95.             [displayView setStringValue: @"0."];
  96.           }
  97.         else
  98.           {
  99.             oldValue = [displayView stringValue];
  100.             [displayView setStringValue: [oldValue stringByAppendingString: @"."]];
  101.           }
  102.       }
  103. }
  104.  
  105. -(void) awakeFromNib
  106. {
  107.     [self clear: self];
  108.     [[displayView window] makeKeyAndOrderFront:nil];
  109. }
  110.  
  111. - (void)operation:(id)sender
  112. {
  113.     if (enteringNumber)
  114.       {
  115.         [self endEditingNumber];
  116.         [self performLastOperation];
  117.         [displayView setStringValue: [displayedNumber stringValue]];
  118.       }
  119.     // no matter what, set the new operation in case the user changes his/her mind
  120.     lastOperation = [sender tag];
  121.  
  122. }
  123.  
  124. - (void)performLastOperation
  125. {
  126.     if (lastOperation == kNoOperator)
  127.       {
  128.         return;
  129.       }
  130.  
  131.     // it is possible to extensively rewrite the following code.  In all cases,
  132.     // displayedNumber is autoreleased, assigned a new value and that new value is
  133.     // retained.  Thus it would reduce the number of lines of code to put the
  134.     // autorelease statement before the nest of if statements, and put the retain
  135.     // statement after the nest of if statements.  However, I've duplicated the
  136.     // statements just to brutally drive home the point that you need to autorelease
  137.     // before you assign over your instance variables, and you need to retain them
  138.     // after you've assigned to them.  Even in the case that none of the if statements
  139.     // are executed, autoreleaseing and immediately retaining the same object is
  140.     // perfectly acceptable.
  141.     
  142.     // This way of detecting NANs is a HACK!  Unfortunately, NaN is not ordered, so
  143.     // if you ask any number if it's equal to NaN, it'll say yes.  So, instead we'll
  144.     // ask if it's equal to an impossible combination of numbers -- zero and one.
  145.     // The only 'number' equal to both is NaN
  146.     if ((([displayedNumber compare: [NSDecimalNumber zero]] == NSOrderedSame) &&
  147.          ([displayedNumber compare: [NSDecimalNumber one]] == NSOrderedSame)) ||
  148.         (([enteredNumber compare: [NSDecimalNumber zero]] == NSOrderedSame) &&
  149.          ([enteredNumber compare: [NSDecimalNumber one]] == NSOrderedSame)))
  150.       {
  151.         [displayedNumber autorelease];
  152.         displayedNumber = [[NSDecimalNumber notANumber] retain];
  153.         return;
  154.       }
  155.     else if (lastOperation == kAddOperator)
  156.       {
  157.         [displayedNumber autorelease];
  158.        displayedNumber = [enteredNumber decimalNumberByAdding: displayedNumber];
  159.         [displayedNumber retain];
  160.       }
  161.     else if (lastOperation == kSubtractOperator)
  162.       {
  163.         [displayedNumber autorelease];
  164.         displayedNumber = [enteredNumber decimalNumberBySubtracting: displayedNumber];
  165.         [displayedNumber retain];
  166.       }
  167.     else if (lastOperation == kMultiplyOperator)
  168.       {
  169.         [displayedNumber autorelease];
  170.         displayedNumber = [enteredNumber decimalNumberByMultiplyingBy: displayedNumber];
  171.         [displayedNumber retain];
  172.       }
  173.     else if (lastOperation == kDivideOperator)
  174.       {
  175.         if ([displayedNumber compare: [NSDecimalNumber zero]] != NSOrderedSame)
  176.           {
  177.             [displayedNumber autorelease];
  178.             displayedNumber = [enteredNumber decimalNumberByDividingBy: displayedNumber];
  179.             [displayedNumber retain];
  180.           }
  181.         else
  182.           {
  183.             [displayedNumber autorelease];
  184.             displayedNumber = [[NSDecimalNumber notANumber] retain];
  185.             [displayedNumber retain];
  186.           }
  187.       }
  188. }
  189.  
  190. - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
  191. {
  192.     return YES;
  193. }
  194.  
  195. - (void)cut:(id)sender
  196. {
  197.     [self copy: self];
  198.     [self clear: self];
  199. }
  200.  
  201. - (void)copy:(id)sender
  202. {
  203.     NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
  204.     [pasteboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: NULL];
  205.     [pasteboard setString: [displayView stringValue] forType: NSStringPboardType];
  206. }
  207.  
  208. - (void)paste:(id)sender
  209. {
  210.     NSPasteboard* pasteboard;
  211.     NSString* pasteValue;
  212.  
  213.     if (!enteringNumber)
  214.       {
  215.         [self beginEditingNumber];
  216.       }
  217.  
  218.     pasteboard = [NSPasteboard generalPasteboard];
  219.     pasteValue = [pasteboard stringForType: NSStringPboardType];
  220.     [displayView setStringValue: [[displayView stringValue] stringByAppendingString: pasteValue]];
  221. }
  222.  
  223. // when self is released, it is necessary to release all of the variables we've retained
  224. -(void)dealloc
  225. {
  226.     [displayedNumber release];
  227.     [enteredNumber release];
  228. }
  229.  
  230. @end
  231.